import * as THREE from 'three'
import { Mesh } from 'three'
import createApp from '../../core'

function createShapeGeometry (dom: HTMLElement) {
  const { camera, scene, update, gui } = createApp(dom)
  camera.position.set(0, 0, 100)
  camera.lookAt(scene.position)

  const mesh = createShapeFromGeometry()
  mesh.position.set(-30, 0, 0)
  scene.add(mesh)

  const bufferMesh = createShapeFromBufferGeometry()
  bufferMesh.position.set(30, 0, 0)
  scene.add(bufferMesh)

  update((time: number) => {
    const angle = time / 1000

    mesh.rotation.set(angle, angle, 0)
    bufferMesh.rotation.set(angle, angle, 0)
  })

  function changeMeshs () {
    generateGeometry(mesh)
    generateGeometry(bufferMesh)
  }

  gui.add(data, 'x', -20, 20).onChange(changeMeshs)
  gui.add(data, 'y', -20, 20).onChange(changeMeshs)
}

const data = {
  x: 0,
  y: 0
}

function createPath () {
  const { x, y } = data
  const Shape = new THREE.Shape()
  Shape.moveTo(x + 5, y + 5)
  Shape.bezierCurveTo(x + 5, y + 5, x + 4, y, x, y)
  Shape.bezierCurveTo(x - 6, y, x - 6, y + 7, x - 6, y + 7)
  Shape.bezierCurveTo(x - 6, y + 11, x - 3, y + 15.4, x + 5, y + 19)
  Shape.bezierCurveTo(x + 12, y + 15.4, x + 16, y + 11, x + 16, y + 7)
  Shape.bezierCurveTo(x + 16, y + 7, x + 16, y, x + 10, y)
  Shape.bezierCurveTo(x + 7, y, x + 5, y + 5, x + 5, y + 5)

  return Shape
}

function createShapeFromGeometry () {
  const shape = createPath()
  const geometry = new THREE.ShapeGeometry(shape)
  const material = new THREE.MeshBasicMaterial({ wireframe: true })
  const mesh = new Mesh(geometry, material)
  return mesh
}

function createShapeFromBufferGeometry () {
  const shape = createPath()
  const geometry = new THREE.ShapeBufferGeometry(shape)
  const material = new THREE.MeshNormalMaterial({ side: THREE.DoubleSide })
  const mesh = new Mesh(geometry, material)
  return mesh
}

function generateGeometry (mesh: THREE.Mesh) {
  const shape = createPath()
  const geometry = new THREE.ShapeBufferGeometry(shape)
  mesh.geometry.dispose()
  mesh.geometry = geometry
}

export {
  createShapeGeometry
}
